from go.core.gotypes import Player
from go.core.util import GameHelp


class Game:
    """
    游戏类
    """

    # 初始化游戏
    def __init__(self, board_size):
        self.board_size = board_size  # 棋盘规格
        self.grid = GameHelp.init_board_grid_points(board_size)  # 棋盘点位
        self.black_go_strings_stones = []  # 黑旗棋链
        self.white_go_strings_stones = []  # 白旗棋链
        self.grid_history = []  # 每一步形成的整个棋盘列表
        self.point_history = []  # 每一步形成的点位列表
        self.current_player = Player.black  # 先手旗手（默认永远是黑旗）
        self.is_game_over = False  # 游戏是否结束

    # 落子后的最终棋盘结果
    def place_go_result(self, point):
        """
        落子后的最终棋盘结果
        本方法不关心当前是黑子还是白子，只要有Point的三个值（row、col、player）即可
        """
        # -------------------------------------------------- 落子 --------------------------------------------------
        cpi = GameHelp.cal_point_index(point.row, point.col, self.board_size)
        self.grid[cpi] = point  # 更新棋盘点位（先把子落下去）
        # -------------------------------------------------- 对手 --------------------------------------------------
        """
        先处理对手的棋链和气
        对手的棋链逻辑：已经存在的棋链不会改变，只会整个棋链被提掉
        """
        # 获取当前对手的棋链
        stones = self.white_go_strings_stones if point.player == Player.black else self.black_go_strings_stones
        result = GameHelp.remove_stones(self.board_size, self.grid, stones)  # 移除没气的棋链（如果有），返回新的棋链
        if point.player == Player.black:
            self.white_go_strings_stones = result
        else:
            self.black_go_strings_stones = result
        # -------------------------------------------------- 自己 --------------------------------------------------
        """
        处理自己的棋链和气
        自己的棋链逻辑：新增独立棋链或合并棋链
        """
        stones2 = self.black_go_strings_stones if point.player == Player.black else self.white_go_strings_stones
        stones3 = GameHelp.get_combine_and_un_combine_stones(stones2, point)  # 获取需要合并的棋链和不需要合并的棋链
        result2 = GameHelp.remove_stones(self.board_size, self.grid, stones3)  # 移除没气的棋链（如果有），返回新的棋链
        if point.player == Player.black:
            self.black_go_strings_stones = result2
        else:
            self.white_go_strings_stones = result2

    # 计算胜负
    def who_win(self):
        black_count = 0
        while_count = 0
        # 同色棋子数统计
        for e in self.grid:
            _p = e.player
            if _p is not None:
                if _p == Player.black:
                    black_count += 1
                else:
                    while_count += 1
        """
        # 同色棋链拥有的气统计
        black_array = []
        white_array = []
        black_stones = self.black_go_strings_stones
        white_stones = self.white_go_strings_stones
        for stone in black_stones:
            for each_point in stone:
                four_neighbors = each_point.neighbors()
                for i in range(0, len(four_neighbors)):
                    x_point = four_neighbors[i][0]
                    y_point = four_neighbors[i][1]
                    if (1 <= x_point <= self.board_size) and (1 <= y_point <= self.board_size):  # 防止越界
                        cpi = GameHelp.cal_point_index(x_point, y_point, self.board_size)
                        black_array.append(cpi)
        for stone in white_stones:
            for each_point in stone:
                four_neighbors = each_point.neighbors()
                for i in range(0, len(four_neighbors)):
                    x_point = four_neighbors[i][0]
                    y_point = four_neighbors[i][1]
                    if (1 <= x_point <= self.board_size) and (1 <= y_point <= self.board_size):  # 防止越界
                        cpi = GameHelp.cal_point_index(x_point, y_point, self.board_size)
                        white_array.append(cpi)
        black_count += len(set(black_array))
        while_count += len(set(white_array))
        """
        if self.board_size == 9:
            while_count += 3.5
        elif self.board_size == 13:
            while_count += 5.5
        elif self.board_size == 19:
            while_count += 7.5
        # print(black_count, while_count)
        return Player.black if black_count > while_count else Player.white
